package cn.lili.common.swagger;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Chopper
 */
@Slf4j
@Configuration
@EnableSwagger2WebMvc
public class Swagger2Config {

	@Value("${swagger.title}")
	private String title;

	@Value("${swagger.description}")
	private String description;

	@Value("${swagger.version}")
	private String version;

	@Value("${swagger.termsOfServiceUrl}")
	private String termsOfServiceUrl;

	@Value("${swagger.contact.name}")
	private String name;

	@Value("${swagger.contact.url}")
	private String url;

	@Value("${swagger.contact.email}")
	private String email;

	private List<ApiKey> securitySchemes() {
		List<ApiKey> apiKeys = new ArrayList<>();
		apiKeys.add(new ApiKey("Authorization", "accessToken", "header"));
		return apiKeys;
	}

	private List<SecurityContext> securityContexts() {
		List<SecurityContext> securityContexts = new ArrayList<>();
		securityContexts.add(SecurityContext.builder().securityReferences(defaultAuth())
				.forPaths(PathSelectors.regex("^(?!auth).*$")).build());
		return securityContexts;
	}

	private List<SecurityReference> defaultAuth() {
		AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
		AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
		authorizationScopes[0] = authorizationScope;
		List<SecurityReference> securityReferences = new ArrayList<>();
		securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
		return securityReferences;
	}

	@Bean
	public Docket goodsRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("商品").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				// .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.goods")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	@Bean
	public Docket memberRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("会员").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.member")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	@Bean
	public Docket promotionRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("促销").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.promotion")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	@Bean
	public Docket storeRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("店铺").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.store")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	@Bean
	public Docket tradeRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("交易").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.trade")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	@Bean
	public Docket settingRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("设置").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.setting")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	@Bean
	public Docket permissionRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("权限").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.permission")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	@Bean
	public Docket otherRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("其他").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.other")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	@Bean
	public Docket commonRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("通用").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.common")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	@Bean
	public Docket distributionRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("分销").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.distribution")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	@Bean
	public Docket statisticsRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("统计").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.statistics")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	@Bean
	public Docket paymentRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("支付").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.payment")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	@Bean
	public Docket passportRestApi() {
		return new Docket(DocumentationType.SWAGGER_2).groupName("登录").apiInfo(apiInfo()).select()
				// 扫描所有有注解的api，用这种方式更灵活
				.apis(RequestHandlerSelectors.basePackage("cn.lili.controller.passport")).paths(PathSelectors.any())
				.build().securitySchemes(securitySchemes()).securityContexts(securityContexts());
	}

	private ApiInfo apiInfo() {
		return new ApiInfoBuilder().title(title).description(description).termsOfServiceUrl(termsOfServiceUrl)
				.contact(new Contact(name, url, email)).version(version).build();
	}
}
